package modules

import (
	"fmt"
	jwt "github.com/appleboy/gin-jwt/v2"
	"github.com/gin-gonic/gin"
	"gspeed/app/dist"
	controller "gspeed/app/http/controller/api"
	"gspeed/app/utils/response"
	"gspeed/bootstrap/global"
	"time"
)

type ginJWT struct {
	identityKey string
}

var JwtMiddleware ginJWT

func (g *ginJWT) New() *jwt.GinJWTMiddleware {
	global.Config.SetDefault("app.name", "gin")
	global.Config.SetDefault("app.key", "gin")

	// 表的那个字段作为唯一标识
	g.identityKey = "user_id"

	middleware, err := jwt.New(&jwt.GinJWTMiddleware{
		// JWT标识
		Realm: global.Config.GetString("app.name"),
		// 服务端密钥
		Key: []byte(global.Config.GetString("app.key")),
		// token 过期时间
		Timeout: 30 * time.Minute,
		// token 更新时间
		MaxRefresh:  30 * time.Minute,
		IdentityKey: g.identityKey,
		// 添加额外业务相关的信息
		PayloadFunc:     g.payloadFunc,
		IdentityHandler: g.identityHandler,
		// 登录逻辑
		Authenticator: controller.AuthController.Login,
		// 登录后验证传入的 token 方法，可在此处写权限验证逻辑
		Authorizator: g.authorizator,
		// 验证失败后的函数调用
		Unauthorized: g.unauthorized,
		// 设置 token 获取位置
		TokenLookup: "header: Authorization, query: token, cookie: jwt",
		// Header 中 token 的头部字段，默认值 Bearer
		TokenHeadName: "Bearer",
		TimeFunc:      time.Now,
		// 登录成功后的函数调用
		LoginResponse: g.loginResponse,
		// 刷新token后的响应
		RefreshResponse: g.refreshResponse,
	})

	if err != nil {
		fmt.Println(err.Error())
	}

	return middleware
}

// 自定义登录成功返回信息
func (g *ginJWT) loginResponse(c *gin.Context, code int, token string, expire time.Time) {
	/*response.Json.SetData(gin.H{
		"token":  token,
		"expire": expire.Format(time.RFC3339),
	}).SetCode(dist.JwtLoginSuccess).Ok(c)*/
	response.Ok(c, response.WithData(gin.H{
		"token":  token,
		"expire": expire.Format(time.RFC3339),
	}))
	return
}

// 刷新token后的响应
func (g *ginJWT) refreshResponse(c *gin.Context, code int, token string, expire time.Time) {
	/*response.Json.SetData(gin.H{
		"token":  token,
		"expire": expire.Format(time.RFC3339),
	}).SetCode(dist.JwtTokenRefreshSuccess).Ok(c)*/
	response.Ok(c, response.WithData(gin.H{
		"token":  token,
		"expire": expire.Format(time.RFC3339),
	}))
	return
}

// 如果认证不通过，则调用此方法处理
func (g *ginJWT) unauthorized(c *gin.Context, httpStatus int, message string) {
	// response.Json.SetHttpStatus(httpStatus).SetCode(dist.JwtTokenInvalid).Err(c)
	response.Err(c, response.WithHttpStatus(httpStatus), response.WithCode(dist.JwtTokenInvalid))
	return
}

// 解析token
func (g *ginJWT) identityHandler(c *gin.Context) interface{} {
	// 返回解析后的数据
	claims := jwt.ExtractClaims(c)
	return gin.H{
		"user_id": claims[g.identityKey],
	}
}

/* token认证处理，返回 true-认证通过
data 是IdentityHandler返回的数据
*/
func (g *ginJWT) authorizator(data interface{}, c *gin.Context) bool {
	user := data.(gin.H)
	//fmt.Printf("%#v",user["user_id"])
	// 如果user的id不为0即通过
	if user["user_id"] != 0 {
		// 把当前user_id设置到上下文
		c.Set("UserId", user["user_id"])
		return true
	}
	return false
}

// 装载数据到jwt
func (g *ginJWT) payloadFunc(data interface{}) jwt.MapClaims {
	if true {
		return jwt.MapClaims{"user_id": 1, "username": "jack"}
	}
	return jwt.MapClaims{}
}
